import { INestApplication, ValidationPipe } from "@nestjs/common";
import { WINSTON_MODULE_NEST_PROVIDER } from "nest-winston";
import { getServerConfig } from "../ormconfig";
import helmet from "helmet";
import rateLimit from "express-rate-limit";
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
import { HttpExceptionFilter } from "@/filters/http-exception.filter";
import { TransformInterceptor } from "@/interceptors/transform.interceptor";
import * as express from "express";
import { logger } from "@/common/log4js/logger.middleware";
import { mw as requestIpMw } from "request-ip";
import { ExceptionsFilter } from "@/filters/exceptions-filter";

export const setupApp = (app: INestApplication) => {
	const config = getServerConfig();
	console.log("config", config);
	// 设置 api 访问前缀
	// app.setGlobalPrefix(config.API_PREFIX);
	// 获取真实 ip
	app.use(requestIpMw({ attributeName: "ip" }));
	// 日志
	app.use(express.json());  // 注意：除了错误级别的中间件，其他的中间件，必须在路由之前进行配置  通过 express.json() 这个中间件，解析表单中的 JSON 格式的数据
	app.use(express.urlencoded({ extended: true }));// 通过 express.urlencoded() 这个中间件，来解析表单中的 url-encoded 格式的数据
	app.use(logger);
	// 使用全局拦截器打印出参
	app.useGlobalInterceptors(new TransformInterceptor());
	// 所有异常
	app.useGlobalFilters(new ExceptionsFilter());
	app.useGlobalFilters(new HttpExceptionFilter());//全局http过滤器
	// 添加全局自动验证管道
	app.useGlobalPipes(
		new ValidationPipe({
			/** 负载对象自动转换 */
			transform: true,
			transformOptions: { enableImplicitConversion: true },
			/** 自动过滤未知参数 */
			whitelist: true
		})
	);
	
	// app.useGlobalGuards()
	// 弊端 -> 无法使用DI -> 无法访问userService
	
	// app.useGlobalInterceptors(new SerializeInterceptor());
	
	// helmet头部安全
	app.use(helmet());
	
	// rateLimit限流
	app.use(
		rateLimit({
			windowMs: 1 * 60 * 1000, // 1 minutes
			max: 300 // limit each IP to 100 requests per windowMs
		})
	);
	
	//初始化Swagger文档
	const swaggerOptions = new DocumentBuilder()
		.setTitle("nest-seed")
		.setDescription("接口文档")
		.setVersion("1.0.0")
		.addBearerAuth()
		.build();
	const document = SwaggerModule.createDocument(app, swaggerOptions);
	// 项目依赖当前文档功能，最好不要改变当前地址
	// 生产环境使用 nginx 可以将当前文档地址 屏蔽外部访问
	SwaggerModule.setup(`${config.API_PREFIX}doc`, app, document);
	
};
